package com.snail.monitor.ui;

import com.snail.monitor.IMonitorCtrl;
import com.snail.monitor.KeyboardAndMouseMonitor;
import com.snail.monitor.MonitorRecord;
import com.snail.monitor.OperateRecordInfo;
import com.snail.util.ProUtils;
import org.apache.commons.lang3.StringUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FilenameFilter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class MainJFrame implements IMonitorCtrl {

    private JFrame frame;
    private JList<String> opRecordList;
    private JList<String> recordsList;
    private JRadioButton runNumUnlimitedRadioBtn;
    private JRadioButton runNumRadioBtn;
    private JTextField runNumberText;
    private TrayIcon trayIcon;
    private SystemTray tray;

    private List<File> recFiles = new ArrayList<>();

    public void CreateJFrame(String title) throws Exception { // 定义一个CreateJFrame()方法
        URL logoUrl = KeyboardAndMouseMonitor.class.getClassLoader().getResource("logo.png");
        URL contactUsUrl = KeyboardAndMouseMonitor.class.getClassLoader().getResource("contactUs.jpg");
        if (SystemTray.isSupported()) {
            tray = SystemTray.getSystemTray();
            Image image = Toolkit.getDefaultToolkit().getImage(logoUrl);
            ActionListener exitListener = new ActionListener() {

                public void actionPerformed(ActionEvent e) {

                    System.exit(0);
                }
            };
            PopupMenu popup = new PopupMenu();
            MenuItem exitMenu = new MenuItem("Exit");
            exitMenu.addActionListener(exitListener);
            popup.add(exitMenu);

            MenuItem showWindMenu = new MenuItem("show");
            showWindMenu.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {

                    getFrame().setVisible(true);
                }
            });
            popup.add(showWindMenu);

            trayIcon = new TrayIcon(image, "鼠标键盘监听器", popup);
            ActionListener actionListener = new ActionListener() {

                public void actionPerformed(ActionEvent e) {

                    trayIcon.displayMessage("Action Event", "An Action Event Has Been Peformed!",
                            TrayIcon.MessageType.INFO);
                }
            };

            trayIcon.setImageAutoSize(true);
            trayIcon.addActionListener(actionListener);

            try {
                tray.add(trayIcon);
            } catch (AWTException e1) {
                e1.printStackTrace();
            }
        }

        JFrame.setDefaultLookAndFeelDecorated(true);
        frame = new JFrame(title);
        frame.setIconImage(Toolkit.getDefaultToolkit().getImage(logoUrl));
        frame.setResizable(false);
        Container container = frame.getContentPane();
        container.setLayout(new BorderLayout(1, 5));
        JPanel newRecordPanel = new JPanel();
        newRecordPanel.setPreferredSize(new Dimension(300, 400));
        newRecordPanel.setLayout(null);
        newRecordPanel.setBounds(0, 0, 300, 400);
        JLabel label = new JLabel("当前录制记录:(shift+F2停止录制)");
        label.setForeground(new Color(0, 0, 200));
        label.setFont(new Font("宋体", 1, 12));
        label.setBounds(10, 5, 300, 15);
        opRecordList = new JList<String>();
        opRecordList.setListData(new String[] {});
        JScrollPane opRecordListScroll = new JScrollPane(opRecordList);
        opRecordListScroll.setBounds(5, 25, 220, 340);
        newRecordPanel.add(opRecordListScroll);
        newRecordPanel.add(label);

        JPanel newRecordBtnPanel = new JPanel();
        newRecordBtnPanel.setBounds(225, 5, 80, 360);
        newRecordBtnPanel.setLayout(null);
        newRecordPanel.add(newRecordBtnPanel);
        container.add(newRecordPanel, BorderLayout.WEST);
        JButton newBtn = new JButton("录制"); // 快捷键  shift+F3
        newBtn.setBounds(5, 60, 60, 25);
        newRecordBtnPanel.add(newBtn);
        newBtn.registerKeyboardAction(new ActionListener() {

            public void actionPerformed(ActionEvent e) {

                startMonitor();
            }
        }, KeyStroke.getKeyStroke(KeyEvent.VK_F3, InputEvent.SHIFT_DOWN_MASK, true), JComponent.WHEN_FOCUSED);
        newBtn.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {

                startMonitor();
            }
        });

        JButton saveBtn = new JButton("保存");
        saveBtn.setBounds(5, 100, 60, 25);
        newRecordBtnPanel.add(saveBtn);
        saveBtn.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent actionevent) {
                showSaveRecordInfoWin();
            }
        });

        ImageIcon contactUsImage = new ImageIcon(Toolkit.getDefaultToolkit().getImage(contactUsUrl));
        Image temp = contactUsImage.getImage().getScaledInstance(60, 60, Image.SCALE_SMOOTH);
        JButton contactUsBtn = new JButton(new ImageIcon(temp));
        contactUsBtn.setBounds(5, 160, 60, 60);
        newRecordBtnPanel.add(contactUsBtn);
        contactUsBtn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                showContactUsWind();
            }
        });

        JPanel recordsPanel = new JPanel();

        recordsPanel.setPreferredSize(new Dimension(300, 400));
        recordsPanel.setLayout(null);
        recordsPanel.setBounds(0, 0, 300, 400);

        container.add(recordsPanel, BorderLayout.CENTER);

        JLabel label1 = new JLabel("历史录制记录:");
        label1.setForeground(new Color(0, 0, 200));
        label1.setFont(new Font("宋体", 1, 12));
        label1.setBounds(10, 5, 200, 15);
        recordsPanel.add(label1);

        recordsList = new JList<String>();
        recordsList.setListData(new String[] {});
        JScrollPane recordsListScroll = new JScrollPane(recordsList);
        recordsListScroll.setBounds(5, 25, 280, 260);
        recordsPanel.add(recordsListScroll);

        JLabel label2 = new JLabel("执行次数:");
        label2.setFont(new Font("宋体", 1, 12));
        label2.setBounds(10, 290, 60, 20);
        recordsPanel.add(label2);

        runNumUnlimitedRadioBtn = new JRadioButton("无限");
        runNumUnlimitedRadioBtn.setBounds(75, 290, 60, 20);
        recordsPanel.add(runNumUnlimitedRadioBtn);

        runNumRadioBtn = new JRadioButton("指定:");
        runNumRadioBtn.setBounds(132, 290, 60, 20);
        runNumRadioBtn.setSelected(true);
        recordsPanel.add(runNumRadioBtn);

        ButtonGroup runNumberBtnGroup = new ButtonGroup();
        runNumberBtnGroup.add(runNumUnlimitedRadioBtn);
        runNumberBtnGroup.add(runNumRadioBtn);

        runNumberText = new JTextField("");
        runNumberText.setBounds(193, 290, 60, 20);
        runNumberText.setText("1");
        recordsPanel.add(runNumberText);

        JButton runBtn = new JButton("执行");
        runBtn.setBounds(160, 320, 80, 20);
        recordsPanel.add(runBtn);

        runBtn.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent actionevent) {
                try {
                    runRecord();
                } catch (Exception e) {
                    JOptionPane.showMessageDialog(getFrame(), "执行脚本出错，请重试或联系系统管理员：" + e.getMessage());
                }
            }
        });

        frame.setVisible(true);
        frame.setSize(600, 400);
        frame.setLocation(200, 200);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        MonitorRecord.getInstance().setCtrl(this);
        MonitorRecord.getInstance().getStopKeys().add(KeyEvent.VK_SHIFT + "");
        MonitorRecord.getInstance().getStopKeys().add(KeyEvent.VK_F2 + "");
        loadRecords();
    }

    private void showContactUsWind() {
        URL contactUsUrl = KeyboardAndMouseMonitor.class.getClassLoader().getResource("contactUs.jpg");
        JDialog dialog = new JDialog(getFrame(), true);
        dialog.setTitle("联系我们");
        dialog.setLocation(getFrame().getX() + 20, getFrame().getY() - 70);
        dialog.setSize(530, 540);
        JLabel label = new JLabel();
        dialog.add(label);
        label.setIcon(new ImageIcon(contactUsUrl));
        dialog.setVisible(true);
    }

    private void showSaveRecordInfoWin() {

        String recName = JOptionPane.showInputDialog(getFrame(), "", "请输入脚本名称", JOptionPane.PLAIN_MESSAGE);
        saveRecordInfo(recName);
    }

    private void loadRecords() {
        File directory = new File(getOpRecPath());
        File[] files = directory.listFiles(new FilenameFilter() {

            public boolean accept(File file, String fileName) {
                return fileName != null && fileName.endsWith(".or");
            }
        });
        Vector<String> fileNames = new Vector<String>();
        recFiles.clear();
        for (File file : files) {
            recFiles.add(file);
            fileNames.add(file.getName().replace(".or", ""));
        }
        recordsList.setListData(fileNames);
    }

    private String getOpRecPath() {
        URL url = MainJFrame.class.getProtectionDomain().getCodeSource().getLocation();
        String path = url.getPath();
        try {
            path = URLDecoder.decode(path, "UTF-8");
        } catch (UnsupportedEncodingException e) {
        }
        File pathFile = new File(path);
        if (pathFile.isFile()) {
            path = pathFile.getParent();
        }
        return path;
    }

    public static void main(String args[]) {
        try {
            new MainJFrame().CreateJFrame(ProUtils.getPropertyValue("appTitle"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public JFrame getFrame() {

        return frame;
    }

    public void setFrame(JFrame frame) {

        this.frame = frame;
    }

    private void runRecord() throws Exception {
        int runCount = getRunCount();
        List<OperateRecordInfo> opRecList = getOperateRecordInfoList();
        if (opRecList == null || opRecList.isEmpty()) {
            JOptionPane.showMessageDialog(getFrame(), "选择的脚本没有需要执行的内容!");
            return;
        }
        runRecord(opRecList, runCount);
    }

    private List<OperateRecordInfo> getOperateRecordInfoList() throws Exception {
        int fileIndex = recordsList.getSelectedIndex();
        if (fileIndex < 0) {
            JOptionPane.showMessageDialog(getFrame(), "请选择需要执行的脚本!");
            return null;
        }
        return MonitorRecord.getInstance().getOpRecsFromFile(getRecFiles().get(fileIndex));
    }

    private int getRunCount() {
        int runCount = 99999;
        if (runNumRadioBtn.isSelected()) {
            String runNumber = runNumberText.getText();
            if (StringUtils.isNumeric(runNumber)) {
                runCount = Integer.parseInt(runNumber);
            }
            if (runCount < 1) {
                runCount = 1;
            }
        }
        return runCount;
    }

    private void runRecord(List<OperateRecordInfo> opRecList, int runCount) {
        try {
            getFrame().setVisible(false);
            Robot robot = new Robot();
            robot.setAutoDelay(100);
            for (int j = 0; j < runCount; j++) {
                for (int i = 0; i < opRecList.size(); i++) {
                    runRecord(robot, opRecList.get(i));
                }
            }
        } catch (AWTException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(getFrame(), "执行出错,被迫中止！");
        } finally {
            getFrame().setVisible(true);
        }
    }

    private void runRecord(Robot robot, OperateRecordInfo info) {
        String opType = info.getOpType();
        String opCode = info.getOpCode();
        String opValue = info.getOpValue();
        if (OperateRecordInfo.OP_TYPE_DELAY.equals(opType)) {
            robot.delay(Integer.parseInt(info.getOpValue()));
        } else if (OperateRecordInfo.OP_TYPE_KEYBOARD.equals(opType)) {
            if (OperateRecordInfo.OP_CODE_KEY_DOWN.equals(opCode)) {
                robot.keyPress(Integer.parseInt(opValue));
            } else if (OperateRecordInfo.OP_CODE_KEY_UP.equals(opCode)) {
                robot.keyRelease(Integer.parseInt(opValue));
            }
        } else if (OperateRecordInfo.OP_TYPE_MOUSE.equals(opType)) {
            String[] xy = opValue.split(",");
            int x = Integer.parseInt(xy[0]);
            int y = Integer.parseInt(xy[1]);
            int inputEventId = InputEvent.BUTTON1_MASK;
            if (OperateRecordInfo.OP_CODE_MOUSE_LEFT_CLICK.equals(opCode)) {
                inputEventId = InputEvent.BUTTON1_MASK;
            } else if (OperateRecordInfo.OP_CODE_MOUSE_RIGHT_CLICK.equals(opCode)) {
                inputEventId = InputEvent.BUTTON3_MASK;
            } else {
                return;
            }
            robot.mouseMove(x, y);
            robot.mousePress(inputEventId);
            robot.mouseRelease(inputEventId);
        }
    }

    public void startMonitor() {
        getFrame().setVisible(false);
        KeyboardAndMouseMonitor.getInstance().startMonitor();
    }

    public void stopMonitor() {
        KeyboardAndMouseMonitor.getInstance().stopMonitor();
        opRecordList.setListData(new Vector(MonitorRecord.getInstance().getOperateRecList()));
        getFrame().setVisible(true);
    }

    private void saveRecordInfo(String recName) {
        try {
            MonitorRecord.getInstance().saveToFile(getOpRecPath() + "/" + recName + ".or");
            opRecordList.setListData(new Vector<String>());
            JOptionPane.showMessageDialog(getFrame(), "保存成功!");
            loadRecords();
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(getFrame(), "保存失败！" + e.getMessage());
        }

    }

    public List<File> getRecFiles() {
        return recFiles;
    }

    public void setRecFiles(List<File> recFiles) {
        this.recFiles = recFiles;
    }
}